package com.dalin.framework.common.utils;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;

import com.dalin.framework.common.utils.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.dalin.framework.common.PropertyConst;

/*****************************************************************************
 * @content: 日期工具类汇总,2010-01-01年与1900-01-01相差40177天 *
 * @author : 那建林 *
 * @crtDate: 2010-02-14 *
 ****************************************************************************/
public final class DateUtils {
	private DateUtils() {
	} // 不允许构造

	private static final Log log = LogFactory.getLog(DateUtils.class);

	/*************************************************************************
	 * @content: 获得系统当前时间，不会有差时区8小时的问题
	 * @return : java.util.Date
	 * @author : 那建林
	 * @crtDate: 2010-02-25 14:53:45
	 * @chaDate: 2010-02-25 14:53:45
	 */
	public static Date getCurrentDate() {
		TimeZone tz = TimeZone.getTimeZone("ETC/GMT-8");
		TimeZone.setDefault(tz);
		return new Date();
	}
	public static Date getCurrentDateNoHis() {
		Calendar cal = Calendar.getInstance();
		int y = cal.get(Calendar.YEAR);
		int m = cal.get(Calendar.MONTH);
		int d = cal.get(Calendar.DATE);
		return DateUtils.getDate(y, m, d);
	}
	public static Date getCurrentDateByHis(int h, int i, int s) {
		Calendar cal = Calendar.getInstance();
		int y = cal.get(Calendar.YEAR);
		int m = cal.get(Calendar.MONTH);
		int d = cal.get(Calendar.DATE);
		return DateUtils.getDate(y, m, d, h, i, s);
	}

	/*************************************************************************
	 * @content: 获得相对某日期后n天的日期
	 * @param : date 参照日期date(参数为Date型数据)
	 * @param : n 计算天数n(参数为int型数据，可正可负，如-5,8等)
	 * @return : date起n天后的日期,返回值为Date类型
	 * @author : 那建林
	 * @crtDate: 2010-02-14
	 * @chaDate: 2010-02-14
	 */
	public static Date getDateAfterDays(Date date, int n) {
		if (date == null)
			return null;
		return new Date(date.getTime() + Long.parseLong("86400000") * n);
	}
	
	
	/*************************************************************************
	 * @content: 获得相对某日期后delay毫秒的日期
	 * @param  : date 参照日期date(参数为Date型数据)
	 * @param  : delay 毫秒数
	 * @return : date起delay毫秒后的日期,返回值为Date类型
	 * @author : 那建林
	 * @crtDate: 2011-11-02 23:24
	 * @chaDate: 2011-11-02 23:24
	 */
	public static Date getDateAfterHours(Date date, long delay) {
		if (date == null)
			return null;
		return new Date(date.getTime() + delay);
	}
	
	public static Date getDatemd(String dateStr) throws ParseException {
		  DateFormat formatFrom = new SimpleDateFormat("MMM dd,yyyy KK:mm:ss aa", Locale.ENGLISH);
		  Date date = formatFrom.parse(dateStr);
		return date;
	}

	
	/*************************************************************************
	 * @content: 将dateStr字符串转换为Date日期型，dateStr格式为:1983-09-09或1983.09.09
	 * @param : dateStr待转换的日期字符串
	 * @return : java.util.Date
	 * @author : 那建林
	 * @crtDate: 2010-02-14
	 * @chaDate: 2010-02-14
	 */
	public static Date getDate(String dateStr) {
		if (StringUtils.isBlank(dateStr))
			return null;
		dateStr = dateStr.trim();
		dateStr = dateStr.replaceAll("\\.", "-");
		SimpleDateFormat df = null;
		if (dateStr.length() > 19) {
			dateStr = dateStr.substring(0, 19);
		}

		if (dateStr.matches("[\\d]{4}")) {
			df = new SimpleDateFormat("yyyy");
		} else if (dateStr.matches("[\\d]{4}-[\\d]{1,2}")) {
			df = new SimpleDateFormat("yyyy-MM");
		} else if (dateStr.matches("[\\d]{4}-[\\d]{1,2}-[\\d]{1,2}")) {
			df = new SimpleDateFormat("yyyy-MM-dd");
		} else if (dateStr
				.matches("[\\d]{4}-[\\d]{1,2}-[\\d]{1,2}[\\s]{1,}[\\d]{1,2}")) {
			df = new SimpleDateFormat("yyyy-MM-dd HH");
		} else if (dateStr
				.matches("[\\d]{4}-[\\d]{1,2}-[\\d]{1,2}[\\s]{1,}[\\d]{1,2}:[\\d]{1,2}")) {
			df = new SimpleDateFormat("yyyy-MM-dd HH:mm");
		} else if (dateStr
				.matches("[\\d]{4}-[\\d]{1,2}-[\\d]{1,2}[\\s]{1,}[\\d]{1,2}:[\\d]{1,2}:[\\d]{1,2}")) {
			df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		} else {
			return null;
		}
		try {
			return df.parse(dateStr);
		} catch (ParseException e) {
			e.printStackTrace();
			return null;
		}
	}

	/*************************************************************************
	 * @content: 根据整型的年度、月份和日生成Date日期
	 * @param : y年(参数为int型数据，年份只能为正数,否则返回当前日期)
	 * @param : m月(参数为int型数据，可正可负，如-5,8等)
	 * @param : d日(参数为int型数据，可正可负，如-5,8等)
	 * @return : 按年月日参数生成的Date类型数据
	 * @author : 那建林
	 * @crtDate: 2010-02-14
	 * @chaDate: 2010-02-14
	 */
	public static Date getDate(int y, int m, int d) {
		if (y <= 0) {
			log.error("year must be positive.");
			throw new IllegalArgumentException();
		}
		Calendar xmas = new GregorianCalendar(y, m - 1, d);
		return xmas.getTime();
	}
	public static Date getDate(int y, int m, int d, int h, int i, int s) {
		if (y <= 0) {
			log.error("year must be positive.");
			throw new IllegalArgumentException();
		}
		Calendar xmas = new GregorianCalendar(y, m - 1, d, h, i, s);
		return xmas.getTime();
	}

	/*************************************************************************
	 * @content: 计算两日期差值天数
	 * @param : d1 起始日期(参数为Date型数据)
	 * @param : d2 结束日期(参数为Date型数据)
	 * @return : d2减去d1的天数,数据为int型
	 * @author : 那建林
	 * @crtDate: 2010-02-14
	 * @chaDate: 2010-02-14
	 */
	public static int getIntervalDays(Date d1, Date d2) {
		if (d1 == null || d2 == null) {
			log.error("待求时间差的两个时间不能为null.");
		}
		Long milon = (d2.getTime() - d1.getTime()) / 86400000;
		return milon.intValue();
	}

	/*************************************************************************
	 * @content: 将Date日期转换为pattern格式的字符串型返回，例：2006-09-08
	 * @param : date 待转换的日期
	 * @param : pattern 待转换成的格式,如:yyyy-MM-dd
	 * @return : String, ex: 2009-06-09
	 * @author : 那建林
	 * @crtDate: 2010-02-14
	 * @chaDate: 2010-02-14
	 */
	public static String formatDate(Date date, String pattern) {
		if (date == null) {
			log.error("待转换的日期不能为null.");
		}
		SimpleDateFormat sdf = new SimpleDateFormat(pattern);
		return sdf.format(date);
	}

	/*************************************************************************
	 * @content: 将Date日期转换为字符串型返回，例：2006-09-08
	 * @param : date 待转换的日期
	 * @return : String, ex: 2009-06-09
	 * @author : 那建林
	 * @crtDate: 2010-02-14
	 * @chaDate: 2010-02-14
	 */
	public static String getYmdStr(Date date) {
		if (date == null)
			return PropertyConst.EMPTY;
		return formatDate(date, PropertyConst.DATE_PATTERN[2]);
	}

	/*************************************************************************
	 * @content: 将Date日期转换为带时分秒的字符串型返回
	 * @param : java.util.Date
	 * @return : String, ex: 2009-06-09 02:04:05
	 * @author : 那建林
	 * @crtDate: 2010-02-14
	 * @chaDate: 2010-02-14
	 */
	public static String getYmdhisStr(Date date) {
		if (date == null)
			return PropertyConst.EMPTY;
		return formatDate(date, PropertyConst.DATE_PATTERN[5]);
	}

	/*************************************************************************
	 * @content: 根据给定参数日期获得日历对象
	 * @param : date 参数日期
	 * @return : 根据date得到的Calendar对象
	 * @author : 那建林
	 * @crtDate: 2010-02-14
	 * @chaDate: 2010-02-14
	 */
	public static Calendar getCalendar(Date date) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		return c;
	}

	/*************************************************************************
	 * @content: 根据指定日期得到year值
	 * @param : 参数日期date(参数为Date型数据)
	 * @return : 根据date得到的年份int值
	 * @author : 那建林
	 * @crtDate: 2010-02-14
	 * @chaDate: 2010-02-14
	 */
	public static int getYearNumber(Date date) {
		Calendar cal = getCalendar(date);
		return cal.get(Calendar.YEAR);
	}

	/*************************************************************************
	 * @content: 根据指定日期得到month值
	 * @param : 参数日期date(参数为Date型数据)
	 * @return : 根据date得到的月份int值
	 * @author : 那建林
	 * @crtDate: 2010-02-14
	 * @chaDate: 2010-02-14
	 */
	public static int getMonthNumber(Date date) {
		Calendar cal = getCalendar(date);
		return cal.get(Calendar.MONTH) + 1;
	}

	/*************************************************************************
	 * @content: 根据指定日期得到day值
	 * @param : date 参数日期(参数为Date型数据)
	 * @return : 根据date得到的天int值
	 * @author : 那建林
	 * @crtDate: 2010-02-14
	 * @chaDate: 2010-02-14
	 */
	public static int getDayNumber(Date date) {
		Calendar cal = getCalendar(date);
		return cal.get(Calendar.DAY_OF_MONTH);
	}

	/*************************************************************************
	 * @content: 根据指定日期得到hour值
	 * @param : date 参数日期(参数为Date型数据)
	 * @return : 根据date得到的小时int值
	 * @author : 那建林
	 * @crtDate: 2010-02-14
	 * @chaDate: 2010-02-14
	 */
	public static int getHourNumber(Date date) {
		Calendar cal = getCalendar(date);
		return cal.get(Calendar.HOUR_OF_DAY);
	}

	/*************************************************************************
	 * @content: 根据指定日期得到minute值
	 * @param : date 参数日期(参数为Date型数据)
	 * @return : 根据date得到的分钟int值
	 * @author : 那建林
	 * @crtDate: 2010-02-14
	 * @chaDate: 2010-02-14
	 */
	public static int getMinuteNumber(Date date) {
		Calendar cal = getCalendar(date);
		return cal.get(Calendar.MINUTE);
	}

	/*************************************************************************
	 * @content: 根据指定日期得到秒数
	 * @param : date 参数日期
	 * @return : 根据date得到的秒数
	 * @author : 那建林
	 * @crtDate: 2010-02-14
	 * @chaDate: 2010-02-14
	 */
	public static int getSecondNumber(Date date) {
		Calendar cal = getCalendar(date);
		return cal.get(Calendar.SECOND);
	}

	/*************************************************************************
	 * @content: 获得指定日期的星期
	 * @param : date 参数日期(参数为Date型数据)
	 * @return : date为星期几,如"星期五",String型数据
	 * @author : 那建林
	 * @crtDate: 2010-02-14
	 * @chaDate: 2010-02-14
	 */
	public static String getDayOfWeek(Date date) {
		Calendar cal = getCalendar(date);
		int bh = cal.get(Calendar.DAY_OF_WEEK);
		return PropertyConst.ARRAY_WEEK[bh - 1];
	}

	/*************************************************************************
	 * @content: 获得指定日期是今年的第几周
	 * @param : date参数日期(参数为Date型数据)
	 * @return : date为第几周,int型数据
	 * @author : 那建林
	 * @crtDate: 2010-02-14
	 * @chaDate: 2010-02-14
	 */
	public static int getWeekPositionOfYear(Date date) {
		Calendar cal = getCalendar(date);
		return cal.get(Calendar.WEEK_OF_YEAR);
	}

	/*************************************************************************
	 * @content: 判断给定年份是否为闰年
	 * @param : y 年份
	 * @return : boolean 是闰年为true
	 * @author : 那建林
	 * @crtDate: 2010-02-15
	 * @chaDate: 2010-02-15
	 */
	public static boolean isLeapYear(int y) {
		return (y % 4 == 0 && y % 100 != 0) || y % 400 == 0;
	}

	/*************************************************************************
	 * @content: 一年中有多少天,简单说就是闰年366，平常年365
	 * @param : y 年份
	 * @return : int y年中有多少天
	 * @author : 那建林
	 * @crtDate: 2010-02-15
	 * @chaDate: 2010-02-15
	 */
	public static int getTotalDaysNumberByYear(int y) {
		if (isLeapYear(y)) {
			return 366;
		}
		return 365;
	}

	/*************************************************************************
	 * @content: 某年某月中有多少天
	 * @param : year 年份
	 * @param : month 月份
	 * @return : int year年month月中一共有多少天
	 * @author : 那建林
	 * @crtDate: 2010-02-15
	 * @chaDate: 2010-02-15
	 */
	public static int getTotalDaysNumberByMonth(int year, int month) {
		Calendar calendar = new GregorianCalendar();
		calendar.set(Calendar.YEAR, year);
		calendar.set(Calendar.MONTH, month - 1);
		return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
	}

	/*************************************************************************
	 * @content: 一年有多少个星期几 , 一年中有52周加1或2天（闫年），所以根据第一天是星期几即可算出
	 * @param : y 年份
	 * @param : dayOfWeek 星期几
	 * @return : int
	 * @author : 那建林
	 * @crtDate: 2010-02-15
	 * @chaDate: 2010-02-16
	 */
	public static int getTotalDayOfWeeksNumOfYear(int year, int dayOfWeek) {
		int rtnInt = 52;
		Calendar cal = getCalendar(getDate(year, 1, 1));
		int newYearDayOfWeek = cal.get(Calendar.DAY_OF_WEEK) - 1;
		boolean isLeapDay = isLeapYear(year)
				&& (dayOfWeek % 7 == newYearDayOfWeek + 1);
		if ((dayOfWeek % 7 == newYearDayOfWeek) || isLeapDay) {
			rtnInt++;
		}
		return rtnInt;
	}

	public static void main(String[] args) {
		System.out.println(getDateAfterDays(getDate("2017-03-29"),99));
		System.out.println(Integer.MAX_VALUE);
	}
}
